package com.lianjia.analysis.aspect;

import com.lianjia.analysis.service.cache.CacheService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 缓存切面，处理带有@Cacheable注解的方法
 */
@Aspect
@Component
public class CacheAspect {

    private static final Logger logger = LoggerFactory.getLogger(CacheAspect.class);

    @Autowired
    private CacheService cacheService;

    /**
     * 定义切点为所有带有@Cacheable注解的方法
     */
    @Pointcut("@annotation(org.springframework.cache.annotation.Cacheable)")
    public void cacheablePointcut() {
    }

    /**
     * 环绕通知，处理缓存逻辑
     */
    @Around("cacheablePointcut()")
    public Object aroundCacheable(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        
        // 获取方法上的Cacheable注解
        Cacheable cacheable = method.getAnnotation(Cacheable.class);
        if (cacheable == null) {
            return joinPoint.proceed();
        }
        
        // 构建缓存键
        String cacheKey = buildCacheKey(cacheable.value(), method.getName(), joinPoint.getArgs());
        
        // 尝试从缓存获取数据
        Object cachedResult = cacheService.get(cacheKey);
        if (cachedResult != null) {
            logger.debug("Cache hit for key: {}", cacheKey);
            return cachedResult;
        }
        
        // 缓存未命中，执行原方法
        logger.debug("Cache miss for key: {}", cacheKey);
        Object result = joinPoint.proceed();
        
        // 将结果存入缓存
        if (result != null) {
            // 默认缓存一小时
            long expireSeconds = 3600;
            cacheService.set(cacheKey, result, expireSeconds);
            logger.debug("Cached result for key: {} with expiration: {} seconds", cacheKey, expireSeconds);
        }
        
        return result;
    }
    
    /**
     * 构建缓存键
     */
    private String buildCacheKey(String[] cacheNames, String methodName, Object[] args) {
        StringBuilder keyBuilder = new StringBuilder();
        
        // 添加缓存名称
        if (cacheNames != null && cacheNames.length > 0) {
            keyBuilder.append(cacheNames[0]).append(":");
        } else {
            keyBuilder.append("default:");
        }
        
        // 添加方法名
        keyBuilder.append(methodName).append(":");
        
        // 添加参数
        if (args != null && args.length > 0) {
            keyBuilder.append(Arrays.deepToString(args));
        } else {
            keyBuilder.append("noargs");
        }
        
        return keyBuilder.toString();
    }
} 